﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using ZilLion.Service.Core.Domain.EntityBase;
using ZilLion.Service.ZilLionOss.Domain.Entitys;
using ZilLion.Service.ZilLionOss.Domain.Requests;
using ZilLion.Service.ZilLionOss.Domain.Responses;
using ZilLion.Service.ZilLionOss.Domain.Services.Interface;

namespace ZilLion.Service.ZilLionOss.Controllers
{
    /// <summary>
    ///     oss 权限
    /// </summary>
    [Route("Api/OssBack/Auth")]
    public class OssAuthController : OssControllerBase
    {
        private readonly IOssRoleService _ossRoleService;
        private readonly IOssRouteService _ossRouteService;
        private readonly IOssUserService _ossUserService;

        public OssAuthController(IOssUserService ossUserService,
            IOssRouteService ossRouteService, IOssRoleService ossRoleService)
        {
            _ossUserService = ossUserService;
            _ossRouteService = ossRouteService;
            _ossRoleService = ossRoleService;
        }

        #region 修改密码

        /// <summary>
        ///     验证密码是否正确
        /// </summary>
        /// <param name="pwd"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("CheckPwdIsValid")]
        [HttpPost]
        public CheckPwdResponse CheckPwdIsValid([FromBody]PwdRequest request, string token = null)
        {
            var useid = GetUserId();
            var entity = _ossUserService.GetOssUserPwdByUserId(useid);
            if (entity != null)
                return new CheckPwdResponse {IsValid = entity.Userpwd == request.Pwd};

            return new CheckPwdResponse {IsValid = false};
        }

        /// <summary>
        ///     保存新密码
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("SaveNewPwd")]
        [HttpPost]
        public ResponseBase SaveNewPwd([FromBody]PwdRequest request, string token = null)
        {
            var useid = GetUserId();
            var entity = _ossUserService.GetOssUserPwdByUserId(useid);
            entity.Userpwd = request.Pwd;
            _ossUserService.SaveUserpwd(entity);
            return new ResponseBase();
        }

        #endregion

        #region 获取岗位信息

        [Route("GetAllRoles")]
        [HttpGet]
        public AllRolesResponse GetAllRoles(string token = null)
        {
            var companyKey = GetZlCompanyKey();
            var entitys = _ossRoleService.GetAllRoles().Where(x => x.RoleId > 0 && x.ZlCompanyKey == companyKey);

            var result = new List<RolesCompleteInfoDto>();
            foreach (var entity in entitys)
            {
                var dto = new RolesCompleteInfoDto
                {
                    RoleDesc = entity.RoleDesc,
                    RoleName = entity.RoleName,
                    RoleId = entity.RoleId,
                    ZlCompanyKey = entity.ZlCompanyKey
                };
                var routes = _ossRouteService.GetRoleRoutes(entity.RoleId);
                dto.Routes = routes.ToArray();
                result.Add(dto);
            }
            return new AllRolesResponse {Roles = result};
        }

        [Route("GetRoleInfo")]
        [HttpGet]
        public RoleResponse GetRoleInfo(long roleid)
        {
            var entity = _ossRoleService.GetRole(roleid);
            var routes = _ossRouteService.GetRoleRoutes(entity.RoleId);
            var dto = new RolesCompleteInfoDto
            {
                RoleDesc = entity.RoleDesc,
                RoleName = entity.RoleName,
                RoleId = entity.RoleId,
                Routes = routes.ToArray(),
                ZlCompanyKey = entity.ZlCompanyKey
            };
            return new RoleResponse {Roleinfo = dto};
        }

        #endregion

        #region 路由信息

        /// <summary>
        ///     强制重置路由到默认状态
        /// </summary>
        /// <param name="routesInfoEntity"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("ForceResetRoutes")]
        [HttpPost]
        public UserCompleteInfoResponse ForceResetRoutes([FromBody]OssRouteInfoEntity[] routesInfoEntity, string token = null)
        {
            var json = JsonConvert.SerializeObject(routesInfoEntity);
            var routes = RecursionGetRoutes(routesInfoEntity);
            var entity = new OssRouteJsonEntity {RouteJson = json, UpdateTime = DateTime.Now.GetNowChinaTime()};
            _ossRouteService.UpdateRouteJson(entity, routes);
            var userid = GetUserId();
            var data = GetUserCompleteInfo(userid);
            return new UserCompleteInfoResponse {User = data};
        }

        /// <summary>
        ///     获取全部路由(除admin和Isconstant以外)
        /// </summary>
        /// <returns></returns>
        [Route("GetAllRoute")]
        [HttpGet]
        public OssAllRouteResponse GetAllRoute(string token=null)
        {
            var zlcompnaykey = GetZlCompanyKey();
            IList<OssRouteInfoEntity> list = (zlcompnaykey ?? string.Empty).ToLower() == "zillion"
                ? _ossRouteService.GetAllRoute().ToList()
                : _ossRouteService.GetRouteByCompanykey(zlcompnaykey).Where(x => x.IsSystem == false).ToList();
            return new OssAllRouteResponse
            {
                Routes = list.Where(x => !(x.IsAdmin ?? false) && !(x.IsConstant ?? false) && !(x.Haschild ?? false))
                    .ToList()
            };
        }
        /// <summary>
        /// 获取指定公司下属所有模块的所有路由
        /// </summary>
        /// <param name="zlcompnaykey"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("GetModuleRoute")]
        [HttpGet]
        public OssAllRouteResponse GetModuleRoute(string zlcompnaykey, string token = null)
        {
          
            IList<OssRouteInfoEntity> list = _ossRouteService.GetRouteByCompanyModule(zlcompnaykey).ToList();
            return new OssAllRouteResponse
            {
                Routes = list.Where(x => !(x.IsAdmin ?? false) && !(x.IsConstant ?? false) && !(x.Haschild ?? false))
                    .ToList()
            };
        }

        #endregion

        #region 保存用户信息

        /// <summary>
        ///     初始化user
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("InitUser")]
        [HttpPost]
        public BasicUserInfoResponse InitUser([FromBody]EditUserRequest request, string token = null)
        {
            var zlcompanykey = GetZlCompanyKey();
            var entity = _ossUserService.InitUser(request.UserName, zlcompanykey);
            if (entity != null)
            {
                var basicUserInfoResponse = new BasicUserInfoDto
                {
                    UserName = entity.UserName,
                    UserPhoneNo = entity.UserPhoneNo,
                    UserId = entity.UserId,
                    UserAvatar = entity.UserAvatar,
                    UserNickName = entity.UserNickName
                };
                return new BasicUserInfoResponse {User = basicUserInfoResponse};
            }
            return new BasicUserInfoResponse {Errormodel = new WebErrorModel {ErrMessage = "初始化用户失败!"}};
        }

        /// <summary>
        ///     修改员工信息
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("SaveUserInfo")]
        [HttpPost]
        public UserCompleteInfoResponse SaveUserInfo([FromBody]EditUserRequest request, string token = null)
        {
            var entity = new OssUserInfoEntity
            {
                UserId = request.UserId,
                UserName = request.UserName,
                UserAvatar = request.UserAvatar,
                UserNickName = request.UserNickName,
                UserPhoneNo = request.UserPhoneNo,
                ZlCompanyKey = GetZlCompanyKey()
            };
            _ossUserService.SaveUserInfo(entity);
            var data = GetUserCompleteInfo(entity.UserId);
            return new UserCompleteInfoResponse {User = data};
        }

        /// <summary>
        ///     修改密码
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        [Route("UpdatePwd")]
        [HttpPost]
        public ResponseBase SaveUserpwd([FromBody]OssUserPwdEntity entity)
        {
            _ossUserService.SaveUserpwd(entity);
            return new ResponseBase();
        }

        /// <summary>
        ///     员工制定岗位
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("SaveUserRoles")]
        [HttpPost]
        public ResponseBase SaveUserRoles([FromBody]UserRolesRequest request, string token = null)
        {
            _ossUserService.SerUserRoles(request.Userid, request.Roleids);
            return new ResponseBase();
        }

        /// <summary>
        ///     岗位设置
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("SaveRole")]
        [HttpPost]
        public SaveRoleResponse SaveRole([FromBody]OssRoleRequest request, string token = null)
        {
            request.ZlCompanyKey = GetZlCompanyKey();
            var entity = _ossUserService.SaveRole(request);
            var dto = new RolesCompleteInfoDto
            {
                RoleDesc = entity.RoleDesc,
                RoleName = entity.RoleName,
                RoleId = entity.RoleId,
                ZlCompanyKey = GetZlCompanyKey()
            };
            var routes = _ossRouteService.GetRoleRoutes(entity.RoleId);
            dto.Routes = routes.ToArray();

            return new SaveRoleResponse {Role = dto};
        }

        /// <summary>
        ///     岗位权限设置
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("SetRoleRoutes")]
        [HttpPost]
        public ResponseBase SetRoleRoutes([FromBody]RoleRoutesSetRequest request, string token = null)
        {
            _ossUserService.SetRoleRoutes(request.Roleid, request.Routepaths);
            return new ResponseBase();
        }

        [Route("DeleteUser")]
        [HttpDelete]
        public ResponseBase DeleteUser(long userid, string token = null)
        {
            _ossUserService.DeleteUser(userid);
            return new ResponseBase();
        }

        [Route("DeleteRole")]
        [HttpDelete]
        public ResponseBase DeleteRole(long roleid, string token = null)
        {
            _ossRoleService.DeleteRole(roleid);
            return new ResponseBase();
        }

        #endregion

        #region 获取用户信息

        [Route("CheckUserExsists")]
        [HttpGet]
        public UserExistsResponse CheckUserExsists(string username, string token = null)
        {
            var entity = _ossUserService.GetUserInfoByUsername(username);


            return new UserExistsResponse {UserExists = entity != null};
        }


        /// <summary>
        ///     获取当前登录信息
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("GetLoginUser")]
        [HttpGet]
        public UserCompleteInfoResponse GetLoginUser(string token = null)
        {
            var userid = GetUserId();
            var data = GetUserCompleteInfo(userid);
            return new UserCompleteInfoResponse {User = data};
        }

        /// <summary>
        ///     获取用户信息
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("GetUserInfo")]
        [HttpGet]
        public UserCompleteInfoResponse GetUserInfo(long userid, string token = null)
        {
            var data = GetUserCompleteInfo(userid);
            return new UserCompleteInfoResponse {User = data};
        }

        /// <summary>
        ///     获取除当前用户以外所有用户信息
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [Route("GetAllUsers")]
        [HttpGet]
        public AllUserResponse GetAllUsers(string token = null)
        {
            var loginuserid = GetUserId();
            var userlist = _ossUserService.GetAllUsers()
                .Where(x => x.UserId != loginuserid && x.ZlCompanyKey == GetZlCompanyKey()).ToList();
            var result = new AllUserResponse {UserList = new List<UserCompleteInfoDto>()};
            foreach (var user in userlist)
            {
                var roles = _ossUserService.GetUserRoles(user.UserId);
                IEnumerable<OssRoleEntity> ossRoleEntities = roles as OssRoleEntity[] ?? roles.ToArray();
                var dto = new UserCompleteInfoDto
                {
                    IsAdmin = ossRoleEntities.Any(x => x.RoleId == -1),
                    UserId = user.UserId,
                    UserName = user.UserName,
                    UserAvatar = user.UserAvatar,
                    UserNickName = user.UserNickName,
                    Remoteroutes = new List<OssRouteInfoEntity>().ToArray(),
                    UserPhoneNo = user.UserPhoneNo,
                    AuthRoutePaths = new List<string>().ToArray(),
                    UserRoles = ossRoleEntities.ToArray()
                };
                result.UserList.Add(dto);
            }

            return result;
        }

        #endregion

        #region pritive  Recursion Methods

        /// <summary>
        ///     把带Child的层次route 过度成平面的结构
        /// </summary>
        /// <param name="routesInfoEntity"></param>
        /// <param name="parentRoute"></param>
        /// <returns></returns>
        private IList<OssRouteInfoEntity> RecursionGetRoutes(IList<OssRouteInfoEntity> routesInfoEntity,
            OssRouteInfoEntity parentRoute = null)
        {
            var result = new List<OssRouteInfoEntity>();
            foreach (var route in routesInfoEntity)
            {
                if (parentRoute != null)
                {
                    route.Path = $"/{parentRoute.Path}/{route.Path}";
                    route.Path = route.Path.Replace("//", "/");
                    route.ParentPath = parentRoute.Path;
                }
                result.Add(route);
                if (route.Children != null && route.Children.Any())
                {
                    var childs = RecursionGetRoutes(route.Children, route);
                    result.AddRange(childs.ToArray());
                    route.Haschild = true;
                }
                else
                {
                    route.Haschild = false;
                }
            }
            return result;
        }


        /// <summary>
        ///     递归寻找指定Name 的路由对象
        /// </summary>
        /// <param name="routesInfoEntitys"></param>
        /// <param name="removeEntity"></param>
        /// <param name="parentRoute"></param>
        /// <returns></returns>
        private void RecursionRemoveRoute(List<OssRouteInfoEntity> routesInfoEntitys, OssRouteInfoEntity removeEntity,
            OssRouteInfoEntity parentRoute = null)
        {
            var parentRoutePath = parentRoute == null ? string.Empty : parentRoute.Path ?? string.Empty;


            var first =
                routesInfoEntitys.FirstOrDefault(
                    x =>
                        $"{parentRoutePath}{x.Path}".Replace("/", string.Empty) ==
                        removeEntity.Path.Replace("/", string.Empty));
            if (first != null)
                routesInfoEntitys.Remove(first);
            else
                foreach (var route in routesInfoEntitys)
                    if (route.Children != null && route.Children.Any())
                        RecursionRemoveRoute(route.Children, removeEntity, route);
        }


        /// <summary>
        ///     获取一个客户的完整信息
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        private UserCompleteInfoDto GetUserCompleteInfo(long userid)
        {
            var userinfo = _ossUserService.GetUserInfo(userid);
            var roleinfos = _ossUserService.GetUserRoles(userinfo.UserId).ToArray(); //获取制定用户的岗位
            var isaamin = roleinfos.Any(x => x.RoleId == -1); //是否是管理员
            {
                #region 递归找到该用户所有授权路由,如果子路由被授权,则认为父节点自动授权

                var userAuthRoutes = _ossUserService.GetOssRoleRoutesByUserid(userinfo.UserId).ToList(); //获取指定用户已授权路由
                var tmproutes = _ossRouteService.GetAllRoute().ToList();
                var constantRoutes = tmproutes.Where(x => x.IsConstant ?? false).ToArray(); //不受权限控制的路由
                var adminRoutes = tmproutes.Where(x => x.IsAdmin ?? false).ToArray(); //不受权限控制的路由
                var alluserAuthRoutes = new List<OssRouteInfoEntity>();
                foreach (var authRoute in userAuthRoutes)
                {
                    var first = tmproutes.FirstOrDefault(x => x.Path == authRoute.RoutePath);

                    if (first != null)
                    {
                        alluserAuthRoutes.Add(first);
                        var parentpath = first.ParentPath;
                        while (parentpath.IsNotNullOrEmpty())
                        {
                            var firstparent = tmproutes.FirstOrDefault(x => x.Path == parentpath);
                            if (firstparent != null)
                            {
                                alluserAuthRoutes.Add(firstparent);
                                parentpath = firstparent.ParentPath ?? string.Empty;
                            }
                            else
                            {
                                parentpath = string.Empty;
                            }
                        }
                    }
                }
                alluserAuthRoutes.AddRange(constantRoutes); //删除list不包括固定路由
                if (!isaamin)
                    alluserAuthRoutes.RemoveRange(adminRoutes); //删除List中必然包括adminroutes

                #endregion

                var routejson = _ossRouteService.GetRouteJson(); //获取路由Json
                var routes = new List<OssRouteInfoEntity>();
                if (routejson != null && routejson.RouteJson.IsNotNullOrEmpty())
                {
                    var resultRoute = JsonConvert.DeserializeObject<OssRouteInfoEntity[]>(routejson.RouteJson).ToList();

                    if (!isaamin) //如果非管理员把非授权路由(黑名单)从全部路由中剔除
                    {
                        #region 排除非权限类的路由(路由黑名单)

                        var allRoutes = _ossRouteService.GetAllRoute().ToList();
                        var gotoRemoveRoutes = allRoutes.ToList();
                        // 非授权路由黑名单(已出去只能admin访问页面)
                        foreach (var userAuthRoute in alluserAuthRoutes)
                        {
                            var first = allRoutes.FirstOrDefault(x => x.Path == userAuthRoute.Path);
                            //当存在授权,则从删除list中删除
                            if (first != null)
                                gotoRemoveRoutes.Remove(first);
                        }

                        #endregion

                        foreach (var route in gotoRemoveRoutes.ToList())
                            RecursionRemoveRoute(resultRoute, route);
                    }
                    routes.AddRange(resultRoute);
                }
                var authpaths = RecursionGetRoutes(routes.ToArray()).Select(x => x.Path).ToList();
                authpaths.Add("/"); //首页是固定的
                authpaths.Add("/home"); //首页是固定的
                authpaths.Add("/home/dashboard"); //首页是固定的
                //把结果路由表递归成平面路由信息,供客户端判断权限
                var result = new UserCompleteInfoDto
                {
                    IsAdmin = isaamin,
                    UserId = userinfo.UserId,
                    UserName = userinfo.UserName,
                    UserAvatar = userinfo.UserAvatar,
                    UserNickName = userinfo.UserNickName,
                    Remoteroutes = routes.ToArray(),
                    AuthRoutePaths = authpaths.ToArray(),
                    UserPhoneNo = userinfo.UserPhoneNo,
                    UserRoles = roleinfos
                };
                return result;
            }
        }

        #endregion
    }
}